package com.touzbi.hss.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import com.touzbi.hss.beans.Patient;
import com.touzbi.hss.beans.Soin;

public class PatientDAO implements AbstractPatientDAO {

	private static final String HIBERNATE_LIST_QUERY = "from Patient";

	private static final String QUERY_PARAM_NAME = "query";
	private static final String HIBERNATE_RESULT_QUERY = "from Patient patient where patient.firstName like "
			+ ":"
			+ QUERY_PARAM_NAME
			+ " or patient.lastName like "
			+ ":"
			+ QUERY_PARAM_NAME;

	private static final String EXCEPTION_NO_PATIENT = "No patient found";
	private static final String EXCEPTION_NO_PATIENT_ID = "No patient found with id: ";
	private static final String HIBERNATE_COUNT_QUERY = "select count(*) from Patient as patient";

	private AbstractDAOFactory daoFactory;

	public PatientDAO(AbstractDAOFactory daoFactory) {
		this.daoFactory = daoFactory;
	}

	private boolean isEmpty(List<Patient> list) {
		return list == null || list.isEmpty();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Patient> getPatientList() throws DAOException {
		List<Patient> result = this.daoFactory.getSession()
				.createQuery(HIBERNATE_LIST_QUERY).list();
		if (isEmpty(result)) {
			throw new DAOException(EXCEPTION_NO_PATIENT);
		}
		return result;
	}

	@Override
	public void addPatient(Patient patient) {
		this.daoFactory.getSession().save(patient);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Patient> getQueryResult(String query) throws DAOException {
		List<Patient> result = this.daoFactory.getSession()
				.createQuery(HIBERNATE_RESULT_QUERY)
				.setParameter(QUERY_PARAM_NAME, query).list();
		if (isEmpty(result)) {
			throw new DAOException(EXCEPTION_NO_PATIENT);
		}
		return result;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Patient> getQueryResult(String query, int idStart, int count)
			throws DAOException {
		List<Patient> result = (List<Patient>) this.daoFactory.getSession()
				.createQuery(HIBERNATE_RESULT_QUERY)
				.setParameter(QUERY_PARAM_NAME, "%" + query + "%")
				.setFirstResult(idStart).setMaxResults(count).list();
		; // XXX Deprecated
			// method -> use
			// named parameters
		if (isEmpty(result)) {
			throw new DAOException(EXCEPTION_NO_PATIENT);
		}
		return result;
	}

	@Override
	public Patient getPatientById(long id) throws DAOException {
		Patient patient = (Patient) this.daoFactory.getSession().get(
				Patient.class, id);
		if (patient == null) {
			throw new DAOException(EXCEPTION_NO_PATIENT_ID + id);
		}
		return patient;
	}

	@Override
	public void addSoin(Soin soin, Patient patient) {
		Session session = this.daoFactory.getSession();
		session.save(patient);
		session.save(soin);
		patient.addSoin(soin);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Patient> getPatientList(int idStart, int count)
			throws DAOException {
		Query query = this.daoFactory.getSession()
				.createQuery(HIBERNATE_LIST_QUERY).setFirstResult(idStart)
				.setMaxResults(count);
		return query.list();
	}

	@Override
	public long getPatientCount() {
		return (long) this.daoFactory.getSession()
				.createQuery(HIBERNATE_COUNT_QUERY).iterate().next();
	}

	@Override
	public long getPatientCount(String query) {
		return (long) this.daoFactory
				.getSession()
				.createQuery(
						HIBERNATE_COUNT_QUERY
								+ " where patient.firstName like ?")
				.setParameter(0, "%" + query + "%").iterate().next();
	}
}
